<template>
  <el-card>
    <div slot="header">
      <div style="width: 60%;display:inline-block;">编辑表单-{{ title }}</div>
      <div style="text-align: right; width: 40%;display:inline-block;">
        <el-button type="primary" plain @click="preview">预览</el-button>
      </div>
    </div>
    <div class="formMainBody">
      <div ref="body" class="body">
        <div class="controlList">
          <div v-for="item in controls" :key="item.value" class="card">
            <div class="header">
              <div class="title">
                <el-divider direction="vertical" />
                {{ item.text }}
              </div>
            </div>
            <div class="list">
              <draggable
                v-model="item.list"
                :allback-on-body="true"
                :sort="false"
                :group="item.group"
                :move="checkIsMove"
              >
                <transition-group>
                  <div v-for="control in item.list" :id="control.Id" :key="control.Id" type="control" class="item">
                    <div class="icon">
                      <icon :icon="control.Icon" />
                    </div>
                    <span>{{ control.Name }}</span>
                  </div>
                </transition-group>
              </draggable>
            </div>
          </div>
        </div>
        <div class="formBody" :style="{width: (contentWidth+4)+'px'}">
          <div class="content">
            <draggable
              v-model="rows"
              class="draggable"
              :sort="true"
              :group="rowsGroup"
              @add="add"
              @end="endSort"
              @remove="remove"
            >
              <transition-group class="draggable-group">
                <div
                  v-for="item in rowList"
                  :id="item.id"
                  :key="item.key"
                  type="item"
                  :class="'item'+(curKey == item.key ? ' active': '')"
                  @click="chiose(item)"
                >
                  <component
                    :is="item.key"
                    :key="item.id"
                    :page-id="pageId"
                    :content-width="contentWidth"
                    v-bind="item"
                    @edit="edit"
                  />
                  <div class="optList">
                    <el-button type="primary" size="mini" icon="el-icon-edit" circle @click="edit(item.id)" />
                    <el-button type="danger" size="mini" icon="el-icon-delete" circle @click="drop(item)" />
                  </div>
                </div>
              </transition-group>
            </draggable>
          </div>
        </div>
        <div class="clear" />
      </div>
    </div>
    <editControl :id="id" :visible.sync="visible" :content-width="contentWidth" :page-id="pageId" @close="close" />
  </el-card>
</template>

<script>
import Vue from 'vue'
import moment from 'moment'
import { GetBody, GetLayout } from '@/customForm/api/page'
import * as layoutApi from '@/customForm/api/pageLayout'
import { GetItems } from '@/customForm/api/pageControl'
import { PageControlClassify, layoutControl } from '@/customForm/config/formConfig'
import draggable from 'vuedraggable'
import editControl from './pageEdit/editControl.vue'
export default {
  components: {
    draggable,
    editControl
  },
  data() {
    return {
      title: null,
      contentWidth: 1920,
      controlGroup: {
        name: 'control',
        pull: 'clone',
        put: false
      },
      layoutGroup: {
        name: 'layout',
        pull: 'clone',
        put: false
      },
      rowsGroup: {
        name: 'page',
        pull: 'clone',
        put: true
      },
      controls: [],
      rowList: [],
      rows: [],
      page: {},
      curKey: null,
      pageId: null,
      visible: false,
      id: null
    }
  },
  computed: {},
  mounted() {
    this.pageId = this.$route.params.id
    if (this.pageId == null) {
      return
    }
    this.initControl()
    this.$nextTick(this.reset)
  },
  methods: {
    moment,
    remove(e) {
      const index = this.rowList.findIndex(c => c.id === e.item.id)
      if (index !== -1) {
        this.rowList.splice(index, 1)
      }
    },
    preview() {
      this.$router.replace({ name: 'pagePreview', params: { id: this.pageId }})
    },
    reset() {
      this.contentWidth = this.$refs.body.offsetWidth - 280
      if (this.contentWidth > 1920) {
        this.contentWidth = 1920
      }
      this.initForm()
    },
    close(isRefresh, id, data, type) {
      if (isRefresh && type === 4) {
        this.refreshDataTable(id)
      } else if (isRefresh) {
        const row = this.rowList.find(c => c.id === id)
        row.title = data.Name
        row.width = data.WidthRatio
        row.height = data.HeightGrid
        row.show = data.Show
        if (row.type === 0) {
          const config = data.ControlConfig.Statistics
          row.item = {
            Icon: config.Icon,
            ValueStyle: config.ValueStyle,
            FontSize: config.FontSize,
            Color: config.Color,
            IsCenter: config.IsCenter,
            IsConfig: config.FormId != null && config.Select != null
          }
        } else if (row.type === 1) {
          const config = data.ControlConfig.Chart
          row.item = {
            ChartType: config.ChartType,
            Title: config.Title,
            YAxis: config.YAxis,
            XAxis: config.XAxis,
            MarkLine: config.MarkLine,
            Legend: config.Legend,
            IsConfig: config.Selects != null && config.Selects.length > 0 && config.GroupBy != null && config.GroupBy.length > 0
          }
        } else if (row.type === 2) {
          const config = data.ControlConfig.CensusTable
          row.item = {
            IsConfig: config.Selects != null && config.Selects.length > 0
          }
        } else if (row.type === 5) {
          row.item = data.ControlConfig.Layout
        } else if (row.type === 6) {
          if (data.ControlConfig == null) {
            row.item = {}
          } else {
            row.item = data.ControlConfig.ControlSet ?? {}
          }
        } else if (row.type === 3) {
          row.item = data.ControlConfig.Search ?? {}
        }
      }
    },
    async refreshDataTable(id) {
      const res = await GetLayout(id, true)
      const row = this.rowList.find(c => c.id === id)
      row.title = res.Name
      row.width = res.WidthRatio
      row.height = res.HeightGrid
      row.show = res.Show
      row.item = res.Table ?? {}
    },
    edit(id) {
      this.id = id
      this.visible = true
    },
    async initForm() {
      const res = await GetBody(this.pageId, true)
      this.title = res.PageName
      if (res.Controls != null) {
        const rows = []
        this.rowList = res.Controls.map(c => {
          const t = this.format(c)
          rows.push({
            Id: c.ControlId,
            itemId: c.Id,
            pid: 0
          })
          return t
        })
        this.rows = rows
      } else {
        this.rowList = []
      }
    },
    chiose(item) {
      if (this.curKey === item.key) {
        this.curKey = null
      } else {
        this.curKey = item.key
      }
    },
    format(control) {
      const t = {
        key: 'c_' + control.Id,
        id: control.Id,
        title: control.Name,
        code: control.Code,
        width: control.WidthRatio,
        height: control.HeightGrid,
        show: control.Show,
        type: control.ControlType,
        item: null,
        children: null
      }
      if (t.type === 0) {
        t.item = control.Statistics
      } else if (t.type === 1) {
        t.item = control.Chart ?? {}
      } else if (t.type === 4) {
        t.item = control.Table ?? {}
      } else if (t.type === 5) {
        t.item = control.Layout ?? {}
        t.children = control.Children
      } else if (t.type === 6) {
        t.item = control.ControlSet ?? {}
      } else if (t.type === 3) {
        t.item = control.Search ?? {}
      } else if (t.type === 2) {
        t.item = control.CensusTable ?? {}
      }
      Vue.component(t.key, function(resolve, reject) {
        require(['@/' + control.ControlPath + '.vue'], resolve)
      })
      return t
    },
    async initControl() {
      const items = await GetItems()
      this.controls = PageControlClassify.map(c => {
        return {
          value: c.value,
          text: c.text,
          list: items.filter(a => a.Classify === c.value),
          group: c.value === '02' ? this.layoutGroup : this.controlGroup
        }
      })
    },
    checkIsMove(e) {
      if (e.relatedContext == null) {
        return false
      }
      const el = e.draggedContext.element
      const name = e.relatedContext.component.$attrs.group.name
      if (el.Classify === '02' && el.Id === layoutControl.row) {
        return name === 'page' || name === 'tab' || name === 'card'
      } else if (el.Classify === '04') {
        return name === 'filter'
      } else {
        return name === 'page' || name === 'row' || name === 'tab' || name === 'card'
      }
    },
    drop(item) {
      const title = '确认删除控件 ' + item.title + '?'
      const that = this
      this.$confirm(title, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        that.submitDrop(item)
      })
    },
    async submitDrop(item) {
      await layoutApi.Delete(item.id)
      this.$message({
        type: 'success',
        message: '删除成功!'
      })
      this.dropItem(item)
    },
    dropItem(item) {
      const index = this.rows.findIndex(c => c.itemId === item.id)
      if (index !== -1) {
        this.rows.splice(index, 1)
      }
      this.rowList = this.rowList.filter(c => c.id !== item.id)
      this.saveSort()
    },
    add(e) {
      const type = e.item.getAttribute('type')
      const id = e.item.id
      let index
      if (type === 'control') {
        index = this.rows.findIndex(c => c.Id === id && c.itemId == null)
      } else {
        index = this.rows.findIndex(c => c.itemId === id)
      }
      this.addControl(index)
    },
    async addControl(index) {
      const t = this.rows[index]
      if (t == null) {
        return
      } else if (t.itemId != null) {
        const res = await layoutApi.Move(t.itemId, 0, true)
        t.pid = 0
        const item = this.format(res)
        this.rowList.push(item)
        this.saveSort()
      } else {
        const add = {
          PageId: this.pageId,
          ControlId: t.Id,
          Sort: index
        }
        const res = await layoutApi.Add(add)
        this.rows[index] = {
          Id: add.ControlId,
          itemId: res.Id,
          pid: 0,
          Classify: res.Classify
        }
        const item = this.format(res)
        this.rowList.push(item)
        this.saveSort()
      }
    },
    async saveSort() {
      let i = 0
      const list = this.rowList.map(c => {
        i = i + 1
        return {
          Id: c.id,
          Value: i
        }
      })
      await layoutApi.SaveSort(list)
    },
    endSort(e) {
      if (this.rowList.length <= 1 || e.newIndex === e.oldIndex) {
        return
      }
      const arr = this.rowList
      const t = arr[e.newIndex]
      const old = arr[e.oldIndex]
      arr[e.newIndex] = old
      arr[e.oldIndex] = t
      this.rowList = [].concat(arr)
      this.saveSort()
    }
  }
}
</script>

<style scoped>
.formMainBody {
  width: 100%;
  text-align: center;
  min-width: 1372px;
}
.formMainBody .body {
  max-width: 2210px;
  min-width: 1372px;
  width: 100%;
  display: block;
  text-align: left;
}

.formMainBody .header {
  padding-left: 10px;
  width: 100%;
  padding-bottom: 2px;
  line-height: 50px;
  border-bottom: 1px solid rgb(0 0 0 / 18%);
  text-align: left;
}
.formMainBody .header .opBtn {
  float: right;
}

.formMainBody .header .title {
  font-size: 1.1rem;
  display: inline-block;
}
.formMainBody .header .title .el-divider--vertical {
  width: 4px;
  margin: 0;
  height: 1.5em;
  margin-top: -6px;
  background-color: #0095ff;
}
.card {
  margin-bottom: 10px;
}
.clear {
  clear: both;
}
.controlList {
  width: 260px;
  float: left;
  border: 1px solid rgb(155 155 155 / 34%);
  min-height: 700px;
}
.controlList .list {
  width: 100%;
}
.controlList .list .item {
  width: 75px;
  margin: 5px;
  display: inline-block;
  height: 80px;
  text-align: center;
  cursor: pointer;
}
.controlList .list .item .icon {
  font-size: 2.2rem;
  height: 55px;
  line-height: 55px;
}
.controlList .list .item span {
  width: 100%;
  line-height: 20px;
  display: inline-block;
  font-size: 14px;
  font-weight: 500;
}
.formBody {
  min-width: 1002px;
  max-width: 1924px;
  text-align: center;
  border: 1px solid #f0f0f052;
  margin-left: 10px;
  float: right;
}
.formBody .content {
  min-width: 1000px;
  max-width: 1922px;
  width: 100%;
  display: inline-block;
  min-height: 800px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  text-align:initial;
  background-color: #f0f0f0;
  margin: 0px;
}
.formBody .content .item {
  float: left;
  margin: 5px;
  position: relative;
  cursor: pointer;
}
.formBody .content .active .optList{
  display: block;
}
.formBody .content .active{
  border: 1px solid #1682e6
}
.formBody .content .optList {
    position: absolute;
    top: -34px;
    right: 0;
    display: none;
}
.dark .formBody .content {
  background-color: #1d1e1f !important;

}
.dark .formBody .content .active{
  border: 1px solid #f0f0f0
}
.content .draggable-group {
    width: 100%;
    min-height: 100px;
    padding-bottom: 70px;
    display: inline-block;
}
</style>
